package com.diy.sigmund.config;

import java.util.Objects;
import org.apache.ibatis.logging.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <br>自定义MyBatis SQL打印日志
 * <br>1、不打印 mappedStatement.getId() 的日志（一般用于批量处理的sql日志）
 * <br>2、不打印默认日志
 * <br>
 * <br>结合org.apache.ibatis.logging.slf4j.Slf4jImpl实现，打印的MyBatis sql日志
 * <br>[2021-08-23 10:16:46.740] [http-nio-8080-exec-2] [DEBUG] org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
 * <br>[2021-08-23 10:16:46.746] [http-nio-8080-exec-2] [DEBUG] org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@671208c1] was not registered for synchronization because synchronization is not active
 * <br>[2021-08-23 10:16:46.746] [http-nio-8080-exec-2] [INFO ] c.d.s.diycommon.spring.interceptor.SqlInterceptor - ==> mapper: com.diy.sigmund.diyuser.mapper.UserAuthMapper.listByUserId
 * <br>[2021-08-23 10:16:46.746] [http-nio-8080-exec-2] [INFO ] c.d.s.diycommon.spring.interceptor.SqlInterceptor - ==> sql: select id, user_id, identity_type, is_external_login, identifier, credential, create_time, update_time from user_auth where user_id = '1'
 * <br>[2021-08-23 10:16:46.751] [http-nio-8080-exec-2] [DEBUG] o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
 * <br>[2021-08-23 10:16:46.752] [http-nio-8080-exec-2] [DEBUG] o.m.spring.transaction.SpringManagedTransaction - JDBC Connection [HikariProxyConnection@570698246 wrapping com.mysql.cj.jdbc.ConnectionImpl@20c1ee87] will not be managed by Spring
 * <br>[2021-08-23 10:16:46.754] [http-nio-8080-exec-2] [DEBUG] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - ==>  Preparing: select id, user_id, identity_type, is_external_login, identifier, credential, create_time, update_time from user_auth where user_id = ?
 * <br>[2021-08-23 10:16:46.770] [http-nio-8080-exec-2] [DEBUG] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - ==> Parameters: 1(String)
 * <br>[2021-08-23 10:16:46.780] [http-nio-8080-exec-2] [TRACE] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - <==    Columns: id, user_id, identity_type, is_external_login, identifier, credential, create_time, update_time
 * <br>[2021-08-23 10:16:46.781] [http-nio-8080-exec-2] [TRACE] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - <==        Row: 1, 1, 1, 0, 18727613660, 123456, 2021-08-19 17:14:08, 2021-08-19 17:14:11
 * <br>[2021-08-23 10:16:46.783] [http-nio-8080-exec-2] [TRACE] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - <==        Row: 2, 1, 3, 0, 钢管男骑士, 123456, 2021-08-19 17:14:44, 2021-08-19 17:14:50
 * <br>[2021-08-23 10:16:46.783] [http-nio-8080-exec-2] [DEBUG] c.d.s.diyuser.mapper.UserAuthMapper.listByUserId - <==      Total: 2
 * <br>[2021-08-23 10:16:46.784] [http-nio-8080-exec-2] [INFO ] c.d.s.diycommon.spring.interceptor.SqlInterceptor - ==> sql执行用时: 38毫秒
 * <br>[2021-08-23 10:16:46.784] [http-nio-8080-exec-2] [DEBUG] org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@671208c1]
 *
 * @author ylm-sigmund
 * @since 2021/8/22 17:12
 */
public class CustomStdOutImpl implements Log {

    private static final Logger log = LoggerFactory.getLogger(CustomStdOutImpl.class);

    private final boolean enabled;

    /**
     * 不打印 mappedStatement.getId() 的日志（一般用于批量处理的sql日志）
     *
     * @param clazz 例如 com.diy.sigmund.diyuser.service.UserAuthService.selectByUserId
     */
    public CustomStdOutImpl(String clazz) {
        // 也可以使用contains("com.diy.sigmund")
        if (Objects.equals("com.diy.sigmund.diyuser.service.UserAuthService.selectByUserId", clazz)
                || clazz.contains("com.diy.sigmund.diyuser.mapper.TestSqlMapper.insert")
                || clazz.contains("com.diy.sigmund.diyuser.mapper.TestSqlMapper.selectPage")
                // 不起作用
                || clazz.contains("com.diy.sigmund.diyuser.mapper.service.impl.TestSqlServiceImpl")
        ) {
            enabled = false;
            return;
        }
        enabled = true;
    }

    @Override
    public boolean isDebugEnabled() {
        return enabled;
    }

    @Override
    public boolean isTraceEnabled() {
        return enabled;
    }

    @Override
    public void error(String s, Throwable e) {
        log.error(s, e);
    }

    @Override
    public void error(String s) {
        log.error(s);
    }

    @Override
    public void debug(String s) {
        if (containsThisString(s)) {
            return;
        }
        log.info(s);
    }

    @Override
    public void trace(String s) {
        if (containsThisString(s)) {
            return;
        }
        log.info(s);
    }

    @Override
    public void warn(String s) {
        log.warn(s);
    }

    /**
     * 不打印默认日志
     *
     * @param s sql日志
     * @return boolean
     */
    private boolean containsThisString(String s) {
        return s.contains("Creating a new SqlSession")
                || s.contains("SqlSession")
                || s.contains("JDBC Connection")
                // 因为有MyBatis拦截器打印不带问号的完整sql语句 SqlInterceptor ，故此处不再打印
                // ||s.contains("Preparing")
                // ||s.contains("Parameters")
                ;
    }
}
